使用Java语言 利用OpenCV,对两种图片相似度对比 | 您所在的位置:网站首页 › java 图片比较 › 使用Java语言 利用OpenCV,对两种图片相似度对比 |
下边是代码部分 import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.opencv.features2d.*; import org.opencv.core.MatOfDMatch; import org.opencv.core.DMatch; public class OpenCVImageSimilarity { public static void main(String[] args) throws IOException { // 加载OpenCV库 // 读取两张图像。准备比对的图片 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 加载OpenCV库NATIVE_LIBRARY_NAME String imageUrl1 = "https://img/0b653e8b-d306-4e15-8e64-4d2212a7434b.jpg"; String imageUrl2 = "https://img/98845b33-0237-45a1-a91d-714d6aba0c3c.jpg"; Mat image1 = readImageFromUrl(imageUrl1); // 调用方法读取网络图片 Mat image2 = readImageFromUrl(imageUrl2); double rdb=rdbSimilar(image1,image2); double hash= meanHash(image1, image2); double hist= histogram(image1, image2); double result=(rdb+hash+hist)/ 3; System.out.println("RDB相似度:" +rdb ); System.out.println("均值哈希算法计算相似度:"+hash); System.out.println("图片相似度(直方图): " + hist); /* if (image1 != null) { // 图片读取成功,可以进行后续处理或保存 // 这里只是示例将图片保存到本地 String outputPath = "output.jpg"; Imgcodecs.imwrite(outputPath, image1); System.out.println("图片保存成功: " + outputPath); } else { System.out.println("图片读取失败"); }*/ // 将图片处理成一样大 // 计算归一化交叉相关(NCC) // double ncc = calculateNCC(image1, image2); // System.out.println("归一化交叉相关(NCC): " + ncc); } private static Mat readImageFromUrl(String imageUrl) { Mat image = null; try { // 使用URL类打开网络图片的输入流 URL url = new URL(imageUrl); BufferedInputStream inputStream = new BufferedInputStream(url.openStream()); // 将输入流解码为OpenCV的Mat对象 byte[] imageData = inputStream.readAllBytes(); image = Imgcodecs.imdecode(new MatOfByte(imageData), Imgcodecs.IMREAD_COLOR); } catch (IOException e) { e.printStackTrace(); } return image; } static double histogram(Mat image1, Mat image2){ Imgproc.resize(image1, image1, image2.size()); Imgproc.resize(image2, image2, image1.size()); // 计算均方差(MSE) double mse = calculateMSE(image1, image2); // System.out.println("均方差(MSE): " + mse); // 计算结构相似性指数(SSIM) double ssim = calculateSSIM(image1, image2); //System.out.println("结构相似性指数(SSIM): " + ssim); // 计算峰值信噪比(PSNR) double psnr = calculatePSNR(image1, image2); // System.out.println("峰值信噪比(PSNR): " + psnr); // 计算直方图 final double similarity = calculateHistogram(image1, image2); // System.out.println("图片相似度(直方图): " + similarity); return similarity; } // 计算均方差(MSE) private static double calculateHistogram(Mat image1, Mat image2) { // 计算直方图 Mat hist1 = calculateHistogram(image1); Mat hist2 = calculateHistogram(image2); // 计算相似度 final double similarity = Imgproc.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL); return similarity; } // 计算均方差(MSE) private static double calculateMSE(Mat image1, Mat image2) { Mat diff = new Mat(); Core.absdiff(image1, image2, diff); Mat squaredDiff = new Mat(); Core.multiply(diff, diff, squaredDiff); Scalar mseScalar = Core.mean(squaredDiff); return mseScalar.val[0]; } // 计算结构相似性指数(SSIM) private static double calculateSSIM(Mat image1, Mat image2) { Mat image1Gray = new Mat(); Mat image2Gray = new Mat(); Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY); Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY); MatOfFloat ssimMat = new MatOfFloat(); Imgproc.matchTemplate(image1Gray, image2Gray, ssimMat, Imgproc.CV_COMP_CORREL); Scalar ssimScalar = Core.mean(ssimMat); return ssimScalar.val[0]; } // 计算峰值信噪比(PSNR) private static double calculatePSNR(Mat image1, Mat image2) { Mat diff = new Mat(); Core.absdiff(image1, image2, diff); Mat squaredDiff = new Mat(); Core.multiply(diff, diff, squaredDiff); Scalar mseScalar = Core.mean(squaredDiff); double mse = mseScalar.val[0]; double psnr = 10.0 * Math.log10(255.0 * 255.0 / mse); return psnr; } // 计算归一化交叉相关(NCC) // private static double calculateNCC(Mat image1, Mat image2) { // Mat image1Gray = new Mat(); // Mat image2Gray = new Mat(); // Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY); // Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY); // MatOfInt histSize = new MatOfInt(256); // MatOfFloat ranges = new MatOfFloat(0, 256); // Mat hist1 = new Mat(); // Mat hist2 = new Mat(); // // Core.normalize(hist1, hist1, 0, 1, Core.NORM_MINMAX); // Core.normalize(hist2, hist2, 0, 1, Core.NORM_MINMAX); // double ncc = Core.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL); // return ncc; // } private static Mat calculateHistogram(Mat image) { Mat hist = new Mat(); // 设置直方图参数 MatOfInt histSize = new MatOfInt(256); MatOfFloat ranges = new MatOfFloat(0, 256); MatOfInt channels = new MatOfInt(0); List images = new ArrayList(); images.add(image); // 计算直方图 Imgproc.calcHist(images, channels, new Mat(), hist, histSize, ranges); return hist; } static double rdbSimilar(Mat img1, Mat img2){ // 加载OpenCV库 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 读取两张图片 /* Mat img1 = Imgcodecs.imread("path/to/your/image1.jpg"); Mat img2 = Imgcodecs.imread("path/to/your/image2.jpg");*/ // 创建ORB特征检测器和描述子提取器 ORB orb = ORB.create(); // 检测图像中的特征点并计算描述子 MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); Mat descriptors1 = new Mat(); Mat descriptors2 = new Mat(); orb.detectAndCompute(img1, new Mat(), keypoints1, descriptors1); orb.detectAndCompute(img2, new Mat(), keypoints2, descriptors2); // 创建描述子匹配器 DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); // 匹配描述子 MatOfDMatch matches = new MatOfDMatch(); matcher.match(descriptors1, descriptors2, matches); // 计算匹配结果的相似度 double maxDist = 0; double minDist = 100; DMatch[] matchArray = matches.toArray(); for (int i = 0; i < matchArray.length; i++) { double dist = matchArray[i].distance; if (dist < minDist) { minDist = dist; } if (dist > maxDist) { maxDist = dist; } } // 输出相似度 double v = 1 - minDist / maxDist; //System.out.println("最小距离:" + minDist); // System.out.println("最大距离:" + maxDist); // System.out.println("RDB相似度:" +v ); return v; } static double meanHash(Mat img1, Mat img2){ Mat grayImg1 = new Mat(); Mat grayImg2 = new Mat(); Imgproc.cvtColor(img1, grayImg1, Imgproc.COLOR_BGR2GRAY); Imgproc.cvtColor(img2, grayImg2, Imgproc.COLOR_BGR2GRAY); // 缩放图像至固定大小 Size targetSize = new Size(8, 8); Mat resizedImg1 = new Mat(); Mat resizedImg2 = new Mat(); Imgproc.resize(grayImg1, resizedImg1, targetSize); Imgproc.resize(grayImg2, resizedImg2, targetSize); // 计算均值哈希值 String hash1 = calculateMeanHash(resizedImg1); String hash2 = calculateMeanHash(resizedImg2); // 计算汉明距离并计算相似度 int hammingDistance = calculateHammingDistance(hash1, hash2); double similarity = 1 - (double) hammingDistance / (targetSize.width * targetSize.height); return similarity; } private static String calculateMeanHash(Mat image) { double sum = 0; int totalPixels = image.rows() * image.cols(); for (int i = 0; i < image.rows(); i++) { for (int j = 0; j < image.cols(); j++) { double pixelValue = image.get(i, j)[0]; sum += pixelValue; } } double mean = sum / totalPixels; StringBuilder hash = new StringBuilder(); for (int i = 0; i < image.rows(); i++) { for (int j = 0; j < image.cols(); j++) { double pixelValue = image.get(i, j)[0]; if (pixelValue >= mean) { hash.append("1"); } else { hash.append("0"); } } } return hash.toString(); } public static int hammingDistance2(int hash1, int hash2){ int num = hash1 ^ hash2; int count = 0; for(; num > 0; count++) { num &= (num - 1); } return count; } private static int calculateHammingDistance(String hash1, String hash2) { int distance = 0; for (int i = 0; i < hash1.length(); i++) { if (hash1.charAt(i) != hash2.charAt(i)) { distance++; } } return distance; } } 下载opencv官方地址:https://opencv.org/releases/ 安装opencv参考地址:https://blog.csdn.net/star1210644725/article/details/131004810?csdn_share_tail={"type"%3A"blog"%2C"rType"%3A"article"%2C"rId"%3A"131004810"%2C"source"%3A"star1210644725"} 如果是linux环境:需要把System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 注释掉。然后在类中加入静态方法 static { OpenCV.LoadShared(); } |
CopyRight 2018-2019 实验室设备网 版权所有 |